package cn.org.xwb.main.utils;

import cn.org.xwb.main.constants.MailConstant;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 和 Redis 相关的工具类
 */
@Component
@Log4j2
public class RedisUtil {

    private RedisUtil() {}

    /**
     * redis template
     */
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 向 redis 中保存字符串类型的 value 值
     *
     * @param key 键
     * @param value 字符串类型的 value 值
     * @param expire 键值对的有效时间，为 null，则永久有效
     * @param expireUnit 有效时间的单位，默认秒
     */
    public boolean setStrVal(String key, Object value, Long expire, TimeUnit expireUnit) {
        try {
            ValueOperations valueOperations = redisTemplate.opsForValue();
            if (Objects.isNull(expire)) {
                valueOperations.set(key, value);
            }
            if (!Objects.isNull(expire) && Objects.isNull(expireUnit)) {
                valueOperations.set(key, value, expire, TimeUnit.SECONDS);
            }
            if (!Objects.isNull(expire) && !Objects.isNull(expireUnit)) {
                valueOperations.set(key, value, expire, expireUnit);
            }
            log.info("向 redis 中保存字符串类型的 value 值成功，key；{}", key);
            return true;
        } catch (Exception e) {
            log.error("向 redis 中保存字符串类型的 value 值失败，key；{}，value：{}", key, value);
            return false;
        }

    }

    /**
     * 向 redis 中保存字符串类型的 value 值
     *
     * @param key 键
     * @param value 字符串类型的 value 值
     * @param expire 键值对的有效时间，为 null，则永久有效，
     *               有效时间单位默认为秒
     */
    public boolean setStrVal(String key, Object value, Long expire) {
        return setStrVal(key, value, expire, null);
    }

    /**
     * 向 redis 中保存字符串类型的 value 值，
     * 默认键值对永久有效
     *
     * @param key 键
     * @param value 字符串类型的 value 值
     */
    public boolean setStrVal(String key, Object value) {
        return setStrVal(key, value, null, null);
    }

    /**
     * 从 redis 中获取字符串类型的 value 值
     *
     * @param key 键
     * @return 字符串类型的 value 值
     */
    public String getStrVal(String key) {
        return (String) redisTemplate.opsForValue().get(key);
    }

    /**
     * 从 redis 中获取字符串类型的 value 值，并以对象形式返回
     *
     * @param key 键
     * @return 对象形式的 value 值
     */
    public Object getStrValToObj(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 从 redis 中获取并删除字符串类型的 value 值
     *
     * @param key 键
     * @return 字符串类型的 value 值
     */
    public String getAndDelStrVal(String key) {
        return (String) redisTemplate.opsForValue().getAndDelete(key);
    }

    /**
     * 从 redis 中获取并删除字符串类型的 value 值，以对象形式返回
     *
     * @param key 键
     * @return 对象形式的 value 值
     */
    public Object getAndDelStrValObj(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 判断 redis 中是否存在指定的键值
     *
     * @param key 键
     * @return true-存在；false-不存在
     */
    public boolean keyValueIsExists(String key) {
        // 尝试从 redis 中获取指定 key 的值
        String value = getStrVal(key);
        // 是否存在指定的键值
        return !Objects.isNull(value);
    }

    /**
     * 判断 redis 中指定的键的值是否等于指定值
     *
     * @param key 键
     * @param val 指定值
     * @return true-相等；false-不相等
     */
    public boolean keyValueEqual(String key, String val) {
        // 尝试从 redis 中获取指定 key 的值
        String value = getStrVal(key);
        // 指定的键的值是否等于指定值
        return val.equals(value);
    }

}
